package com.kaili.controller.web.v1;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.kaili.common.util.ValidList;
import com.kaili.pojo.dto.stowage.*;
import com.kaili.client.service.ILoginUserInfoService;
import com.kaili.common.util.FreemarkUtils;
import com.kaili.common.util.LoginDetailUtils;
import com.kaili.pojo.entity.BaseCar;
import com.kaili.db.service.*;
import com.kaili.common.exception.BaseExcept;
import com.kaili.except.ResponseStatus;
import com.kaili.feign.UserFeignClient;
import com.kaili.pojo.vo.*;
import com.kaili.utils.StowageUtil;
import com.kaili.version.ApiVersion;
import freemarker.template.Configuration;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.*;

import static com.kaili.except.ResponseStatus.RESPONSE_DATA_EMPTY;

@ApiVersion(1)
@RequestMapping("/{api_version}")
@RestController
@Api(tags = "配载发车服务", description = "配载发车相关API")
@Validated
public class StowageController {

    @Autowired
    ILoginUserInfoService loginUserInfoService;
    @Autowired
    IHsOptEwbService ewbService;
    @Autowired
    IHsEwbsStowageService stowageService;
    @Autowired
    Configuration configuration;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    IBaseCarService carService;

    @PostMapping(value = "/stowages")
    @ApiOperation(value = "新增配载发车", notes = "新增配载发车")
    public ResponseStatus doAddStowage(@Validated @RequestBody StowageAddDTO addDTO) throws BaseExcept{
        StowageAddBean addBean=new StowageAddBean();
        BeanUtils.copyProperties(addDTO,addBean);
        int ret = stowageService.doAddStowage(addBean);
        if (ret != 0) {
            return ResponseStatus.STOWAGE_ADD_ERR;
        }
        return ResponseStatus.RESPONSE_OK;
    }

    @PutMapping(value = "/stowages")
    @ApiOperation(value = "修改配载发车", notes = "修改配载发车")
    public ResponseStatus doUpdateStowage(@Validated @RequestBody StowageAddDTO addDTO) throws BaseExcept{
        StowageAddBean addBean=new StowageAddBean();
        BeanUtils.copyProperties(addDTO,addBean);
        int ret = stowageService.doAddStowage(addBean);
        if (ret != 0) {
            return ResponseStatus.STOWAGE_ADD_ERR;
        }
        return ResponseStatus.RESPONSE_OK;
    }

    @GetMapping("/stowages")
    @ApiOperation(value = "分页查询配载数据列表")
    public Page<StowageQueryVO> queryStowageList(@ModelAttribute StowageQueryDTO req) throws BaseExcept {
        if(req.getCur()!=null&&req.getPageSize()!=null){
            Map<Object,Object> param=new HashMap<>();
            param.putAll(new BeanMap(req));
            param.put("siteId", LoginDetailUtils.getSiteId());
            Page<StowageQueryVO> pager = new Page<StowageQueryVO>(req.getCur(), req.getPageSize());
            pager = stowageService.queryStowagePageList(pager,param);
            return pager;
        }
        throw new BaseExcept(ResponseStatus.STOWAGE_QUERY_ERR);
    }


    @GetMapping("/stowages/ewbs/unLoading")
    @ApiOperation(value = "查询未配载的开单数据列表")
    public List<EwbQueryVO> queryUnLoadingEwbList(@ModelAttribute StowageQueryUnLoadDTO req) throws BaseExcept {
        Map<Object,Object> map=new HashMap<>();
        map.putAll(new BeanMap(req));
        map.put("siteId",loginUserInfoService.getLoginSiteId());
        String s = (String)map.get("dispatchSiteIds");
        if(null != s ){
            map.put("dispatchSiteIds",s.split(","));
        }
        return ewbService.queryUnLoadingEwbList(map);
    }

    @PostMapping(value = "/stowages/send")
    @ApiOperation(value = "确认发车", notes = "确认发车")
    public ResponseStatus doConfirmSend(@Size(min = 1,message = "至少包含一个配载单流水号")@RequestBody ValidList<String> operationIds) {
        int ret = stowageService.doConfirmSend(operationIds);
        if (ret != 0) {
            return ResponseStatus.STOWAGE_CONFIRM_ERR;
        }
        BaseCar baseCar;
        for(String  operationId:operationIds){
            baseCar = new BaseCar();
            baseCar.setId(stowageService.selectById(operationId).getCarId());
            baseCar.setCarStatus("在途");
            carService.updateById(baseCar);
        }
        return ResponseStatus.RESPONSE_OK;
    }

    @GetMapping("/stowages/{operationId}/ewbs")
    @ApiOperation(value = "根据配载单id查询托运单信息")
    public List<EwbQueryVO> queryEwbListByStowageNo(@Pattern(regexp = "^[0-9]{0,19}$",message = "配载单流水号应为[0-9]组成的1-19位字符")
                                             @PathVariable("operationId") @ApiParam(value="配载单ID") String operationId) throws BaseExcept {
        Map searchMap = new HashMap();
        searchMap.put("operationId", operationId);
        searchMap.put("siteId", LoginDetailUtils.getSiteId());
        return stowageService.queryEwbListByStowageNo(searchMap);
    }

    @GetMapping("/stowages/{operationId}")
    @ApiOperation(value = "编辑时通过配载单id查询配载信息")
    public StowageInfoDetailQueryVO queryStowageInfoByNo(@Pattern(regexp = "^[0-9]{0,19}$",message = "配载单流水号应为[0-9]组成的1-19位字符")
                                                  @PathVariable("operationId") @ApiParam(value="配载单ID") String operationId) throws BaseExcept {

        StowageInfoDetailQueryVO stowageInfoDetail = new StowageInfoDetailQueryVO();
        //Integer loginSiteId = loginUserInfoService.getLoginSiteId();
        Integer siteId = LoginDetailUtils.getSiteId();
        //查询配载单信息
        Map<String,Object> searchMap = new HashMap<>();
        searchMap.put("operationId",operationId);
        searchMap.put("siteId",siteId);
        StowageInfoVO stowageInfo = stowageService.queryStowageInfo(searchMap);
        if(stowageInfo==null){
            throw new BaseExcept(RESPONSE_DATA_EMPTY);
        }
        stowageInfoDetail.setStowageInfo(stowageInfo);
        //查询配载单已关联托运单列表
        List<EwbQueryVO> linkedEwbList = stowageService.queryEwbListByStowageNo(searchMap);
        stowageInfoDetail.setLinkedEwbList(linkedEwbList);

        //查询未配载托运单
        Map<String,Object> map = new HashMap<String,Object>();
        //map.put("isLoading",0);
        map.put("siteId",siteId);

        Integer[] dispatchSiteIds = new Integer[2];
        dispatchSiteIds[0]=stowageInfo.getDestinationSiteId();
        if(null != stowageInfo.getNextSiteId()){
            dispatchSiteIds[1]=stowageInfo.getNextSiteId();
        }
        map.put("dispatchSiteIds",dispatchSiteIds);
        List<EwbQueryVO>  unLoadingEwbList = ewbService.queryUnLoadingEwbList(map);
        stowageInfoDetail.setUnLoadingEwbList(unLoadingEwbList);

        return stowageInfoDetail;
    }

    @ApiOperation(value = "删除配载单")
    @DeleteMapping("/stowages/{operationId}")
    public ResponseStatus deleteStowage(@Pattern(regexp = "^[0-9]{0,19}$",message = "配载单流水号应为[0-9]组成的1-19位字符")
                                 @PathVariable("operationId") @ApiParam(value="配载单ID") String operationId) {
        if (0 <= stowageService.deleteStowage(operationId)) {
            return ResponseStatus.RESPONSE_OK;
        } else {
            throw new BaseExcept(ResponseStatus.STOWAGE_DEL_ERR);
        }
    }

    @GetMapping("/stowages/html")
    @ApiOperation(value = "获取配载单信息打印")
    public String queryStowagePrint(@NotEmpty(message = "配载单号不得为空")
                                    @RequestParam("stowageNos") @ApiParam(value="配载单号逗号连接字符串") String stowageNos) throws BaseExcept {
        if(StringUtils.isEmpty(stowageNos)){
            throw new BaseExcept(ResponseStatus.PRINT_NULL);
        }
        String logo = userFeignClient.getCompanyLogo(Long.parseLong(LoginDetailUtils.getCompanyCode()));
        JSONObject json= JSON.parseObject(logo);
        List<String> stowageList = Arrays.asList(stowageNos.split(","));
        Map parm = new HashMap();
        parm.put("stowageList",stowageList);
        List<StowageQueryVO>  list=stowageService.queryStowageList(parm);
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                StowageQueryVO bean = list.get(i);
                Map searchMap = new HashMap();
                searchMap.put("operationId", bean.getOperationId());
                searchMap.put("siteId",loginUserInfoService.getLoginSiteId());
                bean.setEwbQueryVOS(stowageService.queryEwbListByStowageNo(searchMap));
            }
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("list",list);
        map.put("companyName", LoginDetailUtils.getCompanyName());
        if(json.get("data") == null || StringUtils.isEmpty(String.valueOf(json.get("data")))){
            map.put("pictureUrl","../api/static/logo.png");
        }else {
            map.put("pictureUrl", json.get("data"));
        }
        return FreemarkUtils.getPrintTemplate(configuration,"stowagePrint", map);
    }

    @GetMapping("/stowages/ewbs/custom")
    @ApiOperation(value = "智能匹配未配载的开单数据")
    public List<String> queryUnLoadingEwbList(@ModelAttribute StowageNodeDTO stowageNodeDTO) throws BaseExcept {
        Map<String,Object> map = new HashMap<>();
        map.put("dispatchSiteIds", stowageNodeDTO.getDispatchSiteIds().split(","));
        map.put("siteId", loginUserInfoService.getLoginSiteId());
        List<EwbQueryVO> ewbs = ewbService.queryUnLoadingEwbList(map);
        if (ewbs.isEmpty()) {
            return null;
        }
        int size = ewbs.size();
        if(size < 10) {
            List<StowageNodeVO> stowageNodeVOS = new ArrayList<>();
            for (EwbQueryVO queryVO : ewbs) {
                StowageNodeVO stowageNodeVO = new StowageNodeVO();
                stowageNodeVO.setOperation(queryVO.getOperationId());
                stowageNodeVO.setVol(queryVO.getStockVol().doubleValue());
                stowageNodeVO.setWeight(queryVO.getStockWeight().doubleValue());
                stowageNodeVOS.add(stowageNodeVO);
            }
            return StowageUtil.findMaxList(stowageNodeVOS, stowageNodeDTO.getVol().doubleValue(), stowageNodeDTO.getWeight().doubleValue());
        } else {
            int vl[] = new int[size];
            int wt[] = new int[size];
            String[] os = new String[size];
            BigDecimal decimal = new BigDecimal(100);
            for (int i=0; i<size; i++) {
                vl[i] = (ewbs.get(i).getStockVol().multiply(decimal)).intValue();
                wt[i] = (ewbs.get(i).getStockWeight().multiply(decimal)).intValue();
                os[i] = ewbs.get(i).getOperationId();
            }

            int W = (stowageNodeDTO.getVol().multiply(decimal)).intValue();
            int n = vl.length;
            int value = (stowageNodeDTO.getWeight().multiply(decimal)).intValue();
            int[][] k = StowageUtil.knapSack(value, wt, vl, n);
            int[] t = StowageUtil.binaryArray(k, W, value, n);
            List<Integer> list = StowageUtil.sackPrint(wt, k, n, t);
            List<String> strings = new ArrayList<>();
            for (Integer i : list) {
                strings.add(os[i]);
            }
            return strings;
        }
    }
}
